package com.xrf;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.sys.user.entity.ChargeRecordEntityTotal;
import com.sys.user.service.ChargeRecordService;
import com.sys.common.config.StaticVariables;
import com.sys.common.util.ResultMsg;
import com.sys.common.util.ShiroUtils;
import com.sys.sys.entity.SysUserEntity;
import com.sys.sys.service.SysUserService;
import com.sys.sys.service.SysUserTokenService;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 登录相关
 */
@RestController
public class SysLoginController extends AbstractController {
    
    @Autowired
    private Producer producer;
    
    @Autowired
    private SysUserService sysUserService;
    
    @Autowired
    private SysUserTokenService sysUserTokenService;
    
    @Autowired
    private ChargeRecordService chargeRecordService;
    
    private Date firstErrorLoginTime;
    private static final int MAX_LOGIN_ATTEMPTS = 5;
    private static final long LOCK_TIME_MILLIS = 20 * 60000L; // 20分钟

    /**
     * 验证码
     */
    @RequestMapping("captcha.jpg")
    public void captcha(HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        // 生成验证码
        String text = producer.createText();
        BufferedImage image = producer.createImage(text);
        // 保存到shiro session
        ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }

    /**
     * 登录
     */
    @RequestMapping(value = "/sys/login", method = RequestMethod.POST)
    public Map<String, Object> login(String username, String password, String captcha) throws IOException {
        SysUserEntity user = sysUserService.queryByUserName(username); // 用户信息
        if (user == null) {
            return ResultMsg.error("账号不存在");
        }
        if (user.getStatus() == 0) { // 账号锁定
            return ResultMsg.error("账号已被锁定,请联系管理员");
        }
        
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String remoteIp = request.getRemoteAddr();
        long spanMillSeconds = Calendar.getInstance().getTime().getTime() - firstErrorLoginTime;
        
        if (user.getErrorLoginCount() != null && user.getErrorLoginCount() >= MAX_LOGIN_ATTEMPTS 
                && spanMillSeconds <= LOCK_TIME_MILLIS && remoteIp.equals(user.getLastErrorIpAddr())) {
            sysUserService.updateUserErrorLoginIp(remoteIp, user.getUserId());
            return ResultMsg.error(403, "失败5次以上，请20分钟后再登陆!");
        }
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (!user.getPassword().equals(new Sha256Hash(password, user.getSalt()).toHex())) {
            if (user.getErrorLoginCount() != null && user.getErrorLoginCount() >= MAX_LOGIN_ATTEMPTS 
                    && spanMillSeconds > LOCK_TIME_MILLIS) {
                user.setErrorLoginCount(0);
            }
            if (user.getErrorLoginCount() == null || (user.getErrorLoginCount() != null && user.getErrorLoginCount() == 0)) {
                sysUserService.updateUserErrorLoginInfo(1, sdf.format(new Date()), remoteIp, user.getUserId());
            } else {
                sysUserService.updateUserErrorLoginInfo(user.getErrorLoginCount() + 1, sdf.format(new Date()), remoteIp, user.getUserId());
            }
            return ResultMsg.error("账号或密码不正确");
        }
        
        try {
            // 登录成功逻辑
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 生成token，并保存到数据库
        return sysUserTokenService.createToken(user.getUserId());
    }

    @RequestMapping(value = "/sys/homeTaskList", method = RequestMethod.POST)
    public Map<String, Object> homeTaskList() throws Exception {
        DecimalFormat df = new DecimalFormat();
        df.setGroupingUsed(false);
        df.setMinimumFractionDigits(2);
        df.setMaximumFractionDigits(2);
        Map<String, Object> params = new HashMap<>();
        params.put("status", "考勤未下发");
        List<ChargeRecordEntityTotal> meterStatusFailList = chargeRecordService.queryTotalList(params);
        double totalMoney = 0d;
        for (ChargeRecordEntityTotal t : meterStatusFailList) {
            if (t.getChargemoney() != null) {
                totalMoney += t.getChargemoney();
            }
        }
        int registerUserNum = sysUserService.queryAppUserRegisterNum();
        int onlineUserNum = 0;
        long curSysMills = System.currentTimeMillis();
        long onlineTimeMills = curSysMills - StaticVariables.onlineOrOfflineMinuteThreshold * 60000;
        synchronized (StaticVariables.appUserIdAndLastViewMills) {
            Set<Long> userIdSet = StaticVariables.appUserIdAndLastViewMills.keySet();
            for (Long key : userIdSet) {
                Long lastViewMills = StaticVariables.appUserIdAndLastViewMills.get(key);
                if (lastViewMills > onlineTimeMills) {
                    onlineUserNum++;
                }
            }
        }
        ResultMsg resultMsg = ResultMsg.ok();
        resultMsg.put("meterStatusFailRecordSize", meterStatusFailList.size());
        resultMsg.put("meterStatusFailTotalMoney", df.format(totalMoney));
        resultMsg.put("homeTaskListMeterStatusFailDetail", meterStatusFailList);
        resultMsg.put("registerUserNum", registerUserNum);
        resultMsg.put("onlineUserNum", onlineUserNum);
        return resultMsg;
    }

    /**
     * 退出
     */
    @RequestMapping(value = "/sys/logout", method = RequestMethod.POST)
    public ResultMsg logout() {
        Long userId = getUserId();
        sysUserTokenService.logout(userId);
        return ResultMsg.ok();
    }
}